home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Web Server / PHP.EXE / pear / PHPDoc / parser / PhpdocParserCore.php < prev    next >
Encoding:
PHP Script  |  2001-02-18  |  27.6 KB  |  662 lines

  1. <?php
  2. /**
  3. * Provides basic parser functions.
  4. *
  5. * Provides basic parser functions to extract doc comments, analyse tags and variable
  6. * declarations.
  7. *
  8. * @version  $Id: PhpdocParserCore.php,v 1.4 2001/02/18 14:45:27 uw Exp $
  9. */
  10. class PhpdocParserCore extends PhpdocParserTags {
  11.                     
  12.     /**
  13.     * Scans code for documented and undocumented phpdoc keywords (classes, functions, class variables, uses, constants).
  14.     *
  15.     * This method is somewhat the heart of the phpdoc parser. It takes a string of 
  16.     * phpcode and extracts all classes, functions, class variables, uses (include and friends), 
  17.     * and constants (define) from it. Extract does not mean that the whole class or another element
  18.     * gets extracted. It does not take the code from the class definition and it's opening 
  19.     * curly brace to the closing one. PHPDoc just extracts the class definition itself and 
  20.     * if available a trailing doc comment. This has some drawbacks: phpdoc can't handle 
  21.     * files that contain more than one class it wouldn't know which method/class variable belongs to 
  22.     * a certain class. It's possible to provide a workaround but phpdoc would slow down dramatically.
  23.     * As PHPDoc does not have a real parser but does a simple grep using a bunch of regular expressions
  24.     * there're indeed more limitations. Nevertheless I doubt that you'll have problems with "normal" code.
  25.     *
  26.     * The search algorithm looks pretty strange but belive me it's fast. I have tried several other ways
  27.     * (really complex regexps >500 chars, preg_match_all + looking backwards for comments, ...) but none was
  28.     * faster. This one takes 13s on my machine to scan the current (14/08/2000) code (7130 lines), the 
  29.     * big RegExp way took more than 5 Minutes, the preg_match_all + looking backwards 52s.
  30.     *
  31.     * @param    string  PHP code to scan.
  32.     * @param    mixed   String of one keyword or array of keywords not to scan for. Known keywords are:
  33.     *                   "classes", "functions", "variables", "uses", "consts".
  34.     * @return   array   Hash of phpdoc elements found, indexed by "variables", "functions", "classes", "consts", "uses".
  35.     * @see      $PHP_BASE, $PHP_COMPLEX, $C_BASE, $C_COMPLEX, extractPhpdoc(), getModuleDoc()
  36.     */                    
  37.     function getPhpdocParagraphs($phpcode, $keywords="none") {
  38.  
  39.         // what are we not looking for?        
  40.         if ( !is_array($keywords) ) {
  41.             if ("none" == $keywords) 
  42.                 $keywords = array ();
  43.             else
  44.                 $keywords = array ( $keywords => true );
  45.         }
  46.         
  47.         $start         = 0;
  48.         $paragraphs    = array(
  49.                                 "classes"   => array(),
  50.                                 "functions" => array(),
  51.                                 "variables" => array(),
  52.                                 "consts"    => array(),
  53.                                 "uses"      => array(),
  54.                                 "modules"   => array()
  55.                         );
  56.  
  57.  
  58.         // remember the documented elements to be able to compare with the list of all elements 
  59.         $variables = array();
  60.         $functions = array();
  61.         $variables = array();
  62.         $constants = array();
  63.         $uses      = array();
  64.         
  65.         //
  66.         // Module docs are somewhat more difficult to grep. Always
  67.         // use this function.
  68.         //
  69.         if (!isset($keywords["modules"]))
  70.             list($paragraphs["modules"], $phpcode) = $this->getModuleDoc($phpcode);
  71.         else
  72.             list( , $phpcode) = $this->getModuleDoc($phpcode);
  73.             
  74.         //
  75.         // Find documented elements
  76.         //
  77.  
  78.         while (true) {
  79.             
  80.             $start = strpos($phpcode, "/**", $start);
  81.             if (0 == (int)$start && "integer" != gettype($start) ) 
  82.                 break;
  83.  
  84.             $end        = strpos($phpcode, "*/", $start);
  85.             $remaining  = trim(substr($phpcode, $end + 2));
  86.             
  87.             if ( !isset($keywords["classes"]) && preg_match($this->PHP_COMPLEX["class"], $remaining, $regs) || preg_match($this->PHP_COMPLEX["class_extends"], $remaining, $regs)) {
  88.                 
  89.                 $paragraphs["classes"][] = array(
  90.                                                  "name"     => $regs[1],
  91.                                                 "extends"   => (isset($regs[2])) ? $regs[2] : "",
  92.                                                 "doc"       => $this->extractPhpdoc(substr($phpcode, $start + 3, ($end-$start) - 2))
  93.                                         );
  94.                 $classes[$regs[1]] = true;
  95.             
  96.             } else if ( !isset($keywords["functions"]) && preg_match($this->PHP_COMPLEX["function"], $remaining, $regs)) {
  97.  
  98.                 $head = substr($remaining, strpos($remaining, $regs[0]) + strlen($regs[0]));
  99.                 $head = substr( trim($this->getValue($head, array( "{" => true) )), 0, -1);
  100.                 $paragraphs["functions"][] = array(
  101.                                                     "name"  => $regs[1],
  102.                                                     "doc"   => $this->extractPhpdoc( substr($phpcode, $start+3, ($end-$start)-2) ),
  103.                                                     "head"  => $head
  104.                                                 );
  105.                 $functions[$regs[1]] = true; 
  106.                                         
  107.             } else if ( !isset($keywords["variables"]) && preg_match($this->PHP_COMPLEX["var"], $remaining, $regs)) {
  108.  
  109.                 if ("=" == $regs[2]) 
  110.                     $value = trim($this->getValue( substr($remaining, strpos($remaining, $regs[0]) + strlen($regs[0]) ), array( ";" => true)));
  111.                 else
  112.                     $value = "";                    
  113.                 
  114.                 $paragraphs["variables"][] = array(
  115.                                                     "name"  => $regs[1],
  116.                                                     "value" => $value,
  117.                                                     "doc"   => $this->extractPhpdoc(substr($phpcode, $start + 3, ($end-$start) - 2))
  118.                                                );
  119.                 $variables[$regs[1]] = true;
  120.                 
  121.             } else if ( !isset($keywords["consts"]) && preg_match($this->PHP_COMPLEX["const"], $remaining, $regs) ) {
  122.             
  123.                 $name = ("" != $regs[2]) ? substr($regs[1], 1, -1) : $regs[1];
  124.                 
  125.                 if (isset($regs[5])) {
  126.                     if ($regs[5])
  127.                         $case = "case insensitive, userdefined: '$regs[5]'";
  128.                     else
  129.                         $case = "case sensitive, userdefined: '$regs[5]'";
  130.                 } else {
  131.                     $case = "default: case sensitive";
  132.                 }
  133.                 
  134.                 $paragraphs["consts"][] = array(
  135.                                                 "name"    => $name,
  136.                                                 "value"   => ("" != $regs[4]) ? substr($regs[3], 1, -1) : $regs[3],
  137.                                                 "case"    => $case,
  138.                                                 "doc"     => $this->extractPhpdoc(substr($phpcode, $start + 3, ($end - $start) - 2))
  139.                                             );
  140.                 $constants[$name] = true;
  141.  
  142.             } else if ( !isset($keywords["uses"]) && preg_match($this->PHP_COMPLEX["use"], $remaining, $regs)) {
  143.  
  144.                 $filename = isset($regs[5]) ? $regs[5] : $regs[4];
  145.                 $paragraphs["uses"][] = array(
  146.                                                 "type"  => $regs[1],
  147.                                                 "file"  => $filename,
  148.                                                 "doc"   => $this->extractPhpdoc(substr($phpcode, $start + 3, ($end - $start) - 2))
  149.                                             );
  150.                 $uses[$filename] = true;
  151.                 
  152.             } 
  153.             
  154.             $start++;
  155.         } 
  156.  
  157.         //
  158.         // Find undocumented elements
  159.         //
  160.         if (!isset($keywords["classes"])) {
  161.         
  162.             preg_match_all($this->PHP_COMPLEX["undoc_class"], $phpcode, $regs, PREG_SET_ORDER);
  163.             reset($regs);
  164.             while (list($k, $data) = each($regs))
  165.                 if (!isset($classes[$data[1]]))
  166.                     $paragraphs["classes"][] = array(
  167.                                                     "name"      => $data[1],
  168.                                                     "extends"   => "",
  169.                                                     "doc"       => ""
  170.                                                 );
  171.  
  172.             preg_match_all($this->PHP_COMPLEX["undoc_class_extends"], $phpcode, $regs, PREG_SET_ORDER);
  173.             reset($regs);
  174.             while (list($k, $data) = each($regs))
  175.                 if (!isset($classes[$data[1]]))
  176.                     $paragraphs["classes"][] = array(
  177.                                                      "name"     => $data[1],
  178.                                                     "extends"   => $data[2],
  179.                                                     "doc"       => ""
  180.                                                 );
  181.  
  182.         }
  183.  
  184.         if (!isset($keywords["functions"])) {
  185.             
  186.             preg_match_all($this->PHP_COMPLEX["undoc_function"], $phpcode, $regs, PREG_SET_ORDER);
  187.             reset($regs);
  188.             while (list($k, $data) = each($regs)) 
  189.                 if (!isset($functions[$data[1]])) {
  190.                                     
  191.                     $head = substr($phpcode, strpos($phpcode, $data[0]) + strlen($data[0]));
  192.                     $head = substr(trim( $this->getValue($head, array( "{" => true) )), 0, -1);
  193.                     $paragraphs["functions"][] = array(
  194.                                                         "name"  => $data[1],
  195.                                                         "doc"   => "",
  196.                                                         "head"  => $head
  197.                                                    );
  198.                 }
  199.  
  200.         }
  201.         
  202.  
  203.         if (!isset($keywords["variables"])) {
  204.  
  205.             preg_match_all($this->PHP_COMPLEX["undoc_var"], $phpcode, $regs, PREG_SET_ORDER);
  206.             reset($regs);
  207.             while (list($k, $data) = each($regs)) 
  208.                 if (!isset($variables[$data[1]])) {
  209.                     
  210.                     if ("=" == $data[2])
  211.                         $value = trim($this->getValue( substr($phpcode, strpos($phpcode, $data[0]) + strlen($data[0]) ), array( ";" => true)));
  212.                    else 
  213.                         $value = "";
  214.                 
  215.                     $paragraphs["variables"][] = array(
  216.                                                         "name"  => $data[1],
  217.                                                         "value" => $value,
  218.                                                         "doc"   => ""
  219.                                                 );
  220.             }
  221.         }
  222.         
  223.         if (!isset($keywords["consts"])) {
  224.  
  225.             preg_match_all($this->PHP_COMPLEX["undoc_const"], $phpcode, $regs, PREG_SET_ORDER);
  226.             reset($regs);
  227.             while (list($k, $data)=each($regs)) {
  228.             
  229.                 $name = (""!=$data[2]) ? substr($data[1], 1, -1) : $data[1];
  230.                 if (!isset($constants[$name])) {
  231.                     
  232.                     if (isset($data[5])) {
  233.                         if ($data[5])
  234.                             $case = "case insensitive, userdefined: '$data[5]'";
  235.                         else
  236.                             $case = "case sensitive, userdefined: '$data[5]'";
  237.                     } else {
  238.                         $case = "default: case sensitive";
  239.                     }
  240.                     
  241.                     $paragraphs["consts"][] = array(
  242.                                                     "name"  => $name,
  243.                                                     "value" => ("" != $data[4]) ? substr($data[3], 1, -1) : $data[3],
  244.                                                     "case"  => $case,
  245.                                                     "doc"    => ""
  246.                                                   );
  247.                 }
  248.             }
  249.         }
  250.         
  251.         if (!isset($keywords["uses"])) {
  252.  
  253.             preg_match_all($this->PHP_COMPLEX["undoc_use"], $phpcode, $regs, PREG_SET_ORDER);
  254.  
  255.             reset($regs);
  256.             while (list($k, $data) = each($regs)) {
  257.             
  258.                 $filename = isset($data[5]) ? $data[5] : $data[4];
  259.                 if (!isset($uses[$filename])) {
  260.                     
  261.                     $paragraphs["uses"][] = array(
  262.                                                     "type"  => $data[1],
  263.                                                     "file"  => $filename,
  264.                                                     "doc"   => ""
  265.                                                 );
  266.                     
  267.                 }
  268.             }
  269.             
  270.         }
  271.  
  272.         return $paragraphs;
  273.     }    // end func getPhpdocParagraphs
  274.     
  275.     /**
  276.     * Does a quick prescan to find modules and classes.
  277.     *
  278.     * @param    string  Code to scan
  279.     * @return   array   Hash of modules and classes found in the given code
  280.     * @access   public
  281.     * @see      getPhpdocParagraphs()
  282.     */
  283.     function getModulesAndClasses($phpcode) {
  284.         
  285.         $para = array();
  286.         list($para["modules"], $phpdcode) = $this->getModuleDoc($phpcode);
  287.         $para["classes"] = $this->getClasses($phpcode);
  288.         
  289.         return $para;
  290.     } // end func getModulesAndClasses
  291.  
  292.     /**
  293.     * Tries to extract a module doc.
  294.     * 
  295.     * The syntax for modules is not final yet. The implementation and meaning of "module" 
  296.     * might change at every time! Please do not ask for implementation details.
  297.     *
  298.     * @param    string  PHP Code to scan
  299.     * @return   array   $module structure: $module[0] = array with module data, 
  300.     *                                      $module[1] = php code without the leading module doc
  301.     */    
  302.     function getModuleDoc($phpcode) {
  303.         
  304.         $module = array();
  305.         
  306.         if (preg_match($this->C_COMPLEX["module_doc"], $phpcode, $regs) ) {
  307.         
  308.             $start          = strlen($regs[0]);
  309.             $end            = strpos($phpcode, "*/", $start);
  310.             $remaining      = substr($phpcode, $end + 2);
  311.             $doc_comment    = substr($phpcode, $start, $end-$start);
  312.             
  313.             // Do we have OO Code? If not, continue.
  314.             if ( !preg_match($this->PHP_COMPLEX["class"], $remaining) && !preg_match($this->PHP_COMPLEX["class_extends"], $remaining) ) {
  315.  
  316.                 // Is there a module tag?
  317.                 if ( preg_match($this->C_COMPLEX["module_tags"], $doc_comment) ) {
  318.                 
  319.                     $doc_comment = $this->extractPhpDoc($doc_comment);
  320.                     $tags = $this->getTags( $doc_comment);
  321.                     $allowed = array (
  322.                                         "module"        => true,
  323.                                         "modulegroup"   => true
  324.                                     );
  325.                                     
  326.                     $tags = $this->analyseTags( $tags, array(), array( "module" => true, "modulegroup" => true) );
  327.                     
  328.                     $module = array (
  329.                                     "doc"       => $doc_comment,
  330.                                     "status"    => "ok",
  331.                                     "name"      => (isset($tags["module"])) ? $tags["module"] : "",
  332.                                     "group"     => (isset($tags["modulegroup"])) ? $tags["modulegroup"] : ""
  333.                                 );
  334.                 
  335.                 } else {
  336.             
  337.                     // No module tag. 
  338.                     // Try the remaining keywords. If one matches it's not a module doc 
  339.                     // assume that the module doc is missing. If none matches assume that
  340.                     // it's a module doc which lacks the module tags.
  341.                     if ( preg_match($this->PHP_COMPLEX["function"], $remaining) ||
  342.                          preg_match($this->PHP_COMPLEX["use"], $remaining) ||
  343.                          preg_match($this->PHP_COMPLEX["const"], $remaining) ||
  344.                          preg_match($this->PHP_COMPLEX["var"], $remaining) 
  345.                         ) {
  346.  
  347.                             $module = array(
  348.                                             "doc"       => "",
  349.                                             "status"    => "missing",
  350.                                             "name"      => "",
  351.                                             "group"     => ""
  352.                                         );
  353.                             $remaining = $phpcode;
  354.                             
  355.                     } else {
  356.  
  357.                         $module = array(
  358.                                         "doc"       => $doc_comment,
  359.                                         "status"    => "tags missing",
  360.                                         "name"      => "",
  361.                                         "group"     => ""
  362.                                         );
  363.  
  364.                     }
  365.  
  366.                 } // end if module_tags
  367.  
  368.             } else {
  369.  
  370.                 $remaining = $phpcode;
  371.  
  372.             } // end if class
  373.  
  374.         } else {
  375.  
  376.             $remaining = $phpcode;
  377.  
  378.         }
  379.  
  380.         return array($module, $remaining);
  381.     } // end func getModuleDoc
  382.     
  383.     /**
  384.     * Returns a list of classes found in the given code.
  385.     *
  386.     * In early versions PHPdoc parsed all the code at once which restulted in huge
  387.     * memory intensive hashes. Now it scans for classes, builds a classtree and 
  388.     * does the parsing step by step, writing information to the destination 
  389.     * (renderer, exporter) as soon as possible. This reduces the memory consumption 
  390.     * dramatically. getPhpdocParagraphs() could be used to extract the class definitions
  391.     * as well but this specialized function is somewhat faster.
  392.     *
  393.     * @param    string              PHP code to scan.
  394.     * @return   array   $classes    Array of classes found in the code. $classes[classname] = extends
  395.     */
  396.     function getClasses($phpcode) {
  397.  
  398.         $classes = array();
  399.  
  400.         preg_match_all($this->PHP_COMPLEX["undoc_class"], $phpcode, $regs, PREG_SET_ORDER);
  401.         reset($regs);
  402.         while (list($k, $data) = each($regs))
  403.             $classes[] = array(
  404.                                 "name"      => $data[1],
  405.                                 "extends"   => ""
  406.                             );
  407.         
  408.         preg_match_all($this->PHP_COMPLEX["undoc_class_extends"], $phpcode, $regs, PREG_SET_ORDER);
  409.         reset($regs);
  410.         while (list($k, $data) = each($regs)) 
  411.             $classes[] = array(
  412.                                 "name"      => $data[1],
  413.                                 "extends"   => $data[2]
  414.                             );
  415.         
  416.         return $classes;
  417.     } // end func getClasses
  418.     
  419.     /**
  420.     * Strips "/xx", "x/" and x from doc comments (x means asterix).
  421.     *
  422.     * @param    string  Doc comment to clean up.
  423.     * @return   string  $phpdoc
  424.     */
  425.     function extractPhpdoc($paragraph) {
  426.  
  427.         $lines = split( $this->PHP_BASE["break"], $paragraph);
  428.         $phpdoc = "";
  429.  
  430.         reset($lines);
  431.         while (list($k, $line)=each($lines)) {
  432.         
  433.             $line = trim($line);
  434.             if ("" == $line)
  435.                 continue;
  436.                 
  437.             if ("*" == $line[0])
  438.                 $phpdoc.= trim(substr($line, 1)) . "\n";
  439.             else 
  440.                 $phpdoc.= $line . "\n";
  441.                 
  442.         }
  443.         
  444.         return substr($phpdoc, 0, -1);
  445.     } // end func extractPhpdoc
  446.     
  447.     /**
  448.     * Extract the description from a PHPDoc doc comment.
  449.     *
  450.     * Every PHPDoc doc comment has the same syntax: /xx[break][x]short description
  451.     * [break][[x]multiple line long description[break]][[x]@list of tags[. This function
  452.     * returns an array of the short description and long description.
  453.     *
  454.     * @param    string                  Doc comment to examine.
  455.     * @return   array   $description    $description[0] = short description (first line),
  456.     *                                   $description[1] = long description (second line upto the first tag)
  457.     */
  458.     function getDescription($phpdoc) {
  459.     
  460.         // find the position of the first doc tag
  461.         $positions = $this->getTagPos($phpdoc);
  462.  
  463.         if (0 == count($positions))
  464.             $desc = trim($phpdoc); // no doc tags
  465.         else
  466.             $desc = trim(substr($phpdoc, 0, $positions[0]["pos"])); // strip tags
  467.  
  468.         $lines = split($this->PHP_BASE["break"], $desc);
  469.             
  470.         if (1 == count($lines) || "" == $desc) {
  471.         
  472.             // only a short description but no long description - or even none of both
  473.             $description = array ($desc, "");
  474.         
  475.         } else {
  476.         
  477.             $sdesc = trim($lines[0]);
  478.             unset($lines[0]);
  479.             
  480.             $description = array ($sdesc, implode("", $lines));
  481.             
  482.         }
  483.     
  484.         return $description;
  485.     } // end func getDescription
  486.     
  487.     /**
  488.     * Scans a code passage for a value.
  489.     *
  490.     * There some cases where you can hardly use a regex to grep a value
  491.     * because the value might contain unescaped charaters that end the value.
  492.     * Value means something like "array ( ";", '\;' );" or "'phpdoc; ';" where
  493.     * the delimiter would be ";".
  494.     *
  495.     * @param    string    The php code to examine.
  496.     * @param    mixed        String of one delimiter or array of delimiters.
  497.     * @return    string    Value found in the code
  498.     * @todo        Racecondition: comments
  499.     */
  500.     function getValue($code, $delimiter) {
  501.         if ("" == $code)
  502.             return "";
  503.  
  504.         if (!is_array($delimiter)) 
  505.             $delimiter = array( $delimiter => true );
  506.  
  507.         $code           = trim($code);
  508.         $len            = strlen($code);
  509.         $enclosed       = false;
  510.         $enclosed_by    = "";
  511.  
  512.         if ( isset($delimiter[$code[0]]) ) {
  513.  
  514.             $i = 1;
  515.  
  516.         } else {
  517.  
  518.             for ($i = 0; $i < $len; $i++) {
  519.  
  520.                 $char = $code[$i];
  521.  
  522.                 if (('"' == $char || "'" == $char) && ($char == $enclosed_by || "" == $enclosed_by) && (0 == $i || ($i > 0 && "\\" != $code[$i - 1]))) {
  523.  
  524.                     if (!$enclosed)
  525.                         $enclosed_by = $char;
  526.                     else 
  527.                         $enclosed_by = "";
  528.  
  529.                     $enclosed = !$enclosed;
  530.  
  531.                 }
  532.                 if (!$enclosed && isset($delimiter[$char]))
  533.                     break;
  534.  
  535.             }
  536.  
  537.         }
  538.  
  539.         return substr($code, 0, $i);
  540.     } // end func getValue
  541.  
  542.     /**
  543.     * Analyses a code snipped and returns the type and value of the first variable found.
  544.     *
  545.     * With version 0.3 PHPDoc tries to analyse variable declarations to find 
  546.     * type and value. This is used to analyse class variable declarations and 
  547.     * optional function arguments.
  548.     * 
  549.     * Note that all regular expressions in this function start with "^". That means
  550.     * you have to do some preparations to the code snippet you're passing to this
  551.     * function.
  552.     *
  553.     * @param    string              PHP code to analyse
  554.     * @param    boolean             Flag indicating the "type" of code to analyse. Optional 
  555.     *                               function parameters and class variables have a slightly 
  556.     *                               different syntax for arrays. By default function parameters are expected.
  557.     * @return array     $vartype    $vartype[0] = type, $vartype[1] = value, $vartype[2] = raw value
  558.     */
  559.     function getVariableTypeAndValue($code, $flag_args = true) {
  560.  
  561.         $type       = "unknown";
  562.         $value      = "unknown";
  563.         $raw_value  = $code;
  564.  
  565.         //
  566.         // Do not change the order the function tries to find out the type.
  567.         //
  568.  
  569.         if (preg_match($this->PHP_COMPLEX["type_boolean"], $code, $regs)) {
  570.  
  571.             $type       = "boolean";
  572.             $raw_value  = $regs[0];
  573.             $value      = $regs[0];
  574.  
  575.         } else if (preg_match( $this->PHP_COMPLEX["type_string_enclosed"], $code, $regs)) {
  576.  
  577.             $type       = "string";
  578.             $raw_value  = $regs[0];
  579.             $value      = $regs[0];
  580.  
  581.         }    else if (preg_match( $this->PHP_COMPLEX["type_int_oct"], $code, $regs)) {
  582.  
  583.             $type       = "integer (octal)";
  584.             $raw_value  = $regs[0];
  585.             $value      = preg_replace("@\s@", "", $regs[0]);
  586.             if ((int)$value != $value)
  587.                 $type .= " [warning: out of integer range, possible overflow trouble]";
  588.             $value      = octdec($value)." ($value)";
  589.  
  590.  
  591.         } else if (preg_match( $this->PHP_COMPLEX["type_int_hex"], $code, $regs)) {
  592.  
  593.             $type           = "integer (hexadecimal)";
  594.             $raw_value      = $regs[0];
  595.             $value          = preg_replace("@\s@", "", $regs[0]);
  596.             if ((int)$value != $value)
  597.                 $type .= " [warning: out of integer range, possible overflow trouble]";
  598.             $value          = hexdec($value)." ($value)";
  599.  
  600.         } else if (preg_match( $this->PHP_COMPLEX["type_float_exponent"], $code, $regs)) {
  601.         
  602.             $type           = "float";
  603.             $raw_value      = $regs[0];
  604.             $value          = (string)preg_replace("@\s@", "", $regs[0]);
  605.             if ( (float)$value != $value ) 
  606.                 $type .= " [warning: out of float range]";
  607.             $value                = (float)$value;
  608.     
  609.         } else if (preg_match( $this->PHP_COMPLEX["type_float"], $code, $regs)) {
  610.  
  611.             $type           = "float";
  612.             $raw_value      = $regs[0];
  613.             $value          = preg_replace("@\s@", "", $regs[0]);
  614.             if ( (float)$value != $value ) 
  615.                 $type .= " [warning: out of float range]";
  616.             $value          = (float)$value;
  617.     
  618.         } else if (preg_match( $this->PHP_COMPLEX["type_number"], $code, $regs)) {
  619.     
  620.             $value          = preg_replace("@\s@", "", $regs[0]);
  621.             $raw_value      = $regs[0];
  622.             
  623.             if ( (int)$value == $value ) {
  624.  
  625.                 $type  = "integer";
  626.                 $value = (int)$value;
  627.  
  628.             } else {
  629.  
  630.                 $type = "float";
  631.                 if ( (float)$value != $value )
  632.                     $type.=" [warning: out of float range]";
  633.                 $value = (float)$value;
  634.  
  635.             }
  636.     
  637.         } else if ($flag_args && preg_match( $this->PHP_COMPLEX["type_empty_array"], $code, $regs)) {
  638.             
  639.             $value      = "array()";
  640.             $raw_value  = $regs[0];
  641.             $type       = "array";
  642.             
  643.         } else if (!$flag_args && preg_match( $this->PHP_COMPLEX["type_array"], $code, $regs)) {
  644.         
  645.             $value = $this->getValue( $code, array(";" => true));
  646.             // strpos() is twice as fast as substr()
  647.             if ( 0 == strpos($value, "array")) 
  648.                 $type = "array";
  649.             $raw_value == $value;
  650.         
  651.         } else if (preg_match( $this->PHP_COMPLEX["type_string"], $code, $regs)) {
  652.  
  653.             $type       = "string";
  654.             $raw_value  = $regs[0];
  655.             $value      = $regs[0];
  656.         } 
  657.  
  658.         return array($type, $value, $raw_value);
  659.     } // end func getVariableTypeAndValue
  660.     
  661. } // end class PhpdocParserObject
  662. ?>